import os
import os.path
import time
import json
import matplotlib.pyplot as plt


class TicTocManager:
    """单例类，用于管理所有计时器的数据"""
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
            cls._instance.data = {}  # 存储结构：{msg: [times]}
        return cls._instance

    def record(self, msg: str, duration: float):
        """记录计时数据"""
        if msg not in self.data:
            self.data[msg] = []
        self.data[msg].append(duration)

    def save_to_file(self, filename: str):
        """保存数据到JSON文件"""
        with open(filename, 'w') as f:
            json.dump(self.data, f, indent=2)

    def load_from_file(self, filename: str, post_fix=''):
        """读取到JSON文件"""
        with open(filename, 'r') as f:
            data = json.load(f)
            for key,val in data.items():
                self.data[key+'     '+post_fix] = val

    def load_from_files(self, filename_list: list):
        """读取到JSON文件"""
        for filename in filename_list:
            self.load_from_file(filename, os.path.basename(filename).split('.')[0])

    def plot_comparison(self, title: str = 'Performance Comparison'):
        """绘制智能对比曲线"""
        plt.figure(figsize=(12, 10))

        # 数据预处理：按前缀分组
        grouped_data = {}
        for full_key, durations in self.data.items():
            # 分割前缀和后缀
            parts = full_key.split('     ')
            prefix = parts[0]
            postfix = parts[1] if len(parts) > 1 else ''

            if prefix not in grouped_data:
                grouped_data[prefix] = {}
            grouped_data[prefix][postfix] = durations

        # 配置可视化参数
        colors = plt.cm.tab10.colors  # 使用matplotlib标准色环
        markers = ['o', 's', '^', 'D', 'v', '<', '>', 'p', '*', 'h']

        # 绘制分组曲线
        for idx, (prefix, variants) in enumerate(grouped_data.items()):
            color = colors[idx % len(colors)]

            for sub_idx, (postfix, durations) in enumerate(variants.items()):
                marker = markers[sub_idx % len(markers)]
                label = f"{prefix} ({postfix})" if postfix else prefix

                plt.plot(durations,
                         label=label,
                         color=color,
                         marker=marker,
                         linestyle='-',
                         linewidth=2,
                         markersize=8,
                         alpha=0.8)

        # 增强可视化效果
        plt.title(title, fontsize=14, pad=20)
        plt.xlabel('Run Sequence', fontsize=12)
        plt.ylabel('Time (ms)', fontsize=12)
        # plt.grid(True, linestyle='--', alpha=0.6)

        # 新增代码：设置双层网格
        from matplotlib.ticker import MultipleLocator, AutoMinorLocator
        ax = plt.gca()
        ax.yaxis.set_minor_locator(AutoMinorLocator(n=5))  # 每个主刻度间5个次刻度

        # 主网格（保持原有样式）
        plt.grid(which='major',
                 linestyle='--',
                 linewidth=0.8,
                 alpha=0.6)

        # 次网格（新增更密集的网格）
        plt.grid(which='minor',
                 linestyle=':',
                 linewidth=0.5,
                 alpha=0.4)

        # 优化图例布局
        plt.legend(bbox_to_anchor=(1.05, 1),
                   loc='upper left',
                   borderaxespad=0.,
                   fontsize=10,
                   title="Legend (Prefix - Variant)")

        plt.tight_layout()
        plt.show()


class TicToc:
    """增强版计时器"""

    def __init__(self, msg: str, with_manager=False):
        self.msg = msg
        self.with_manager = with_manager
        if self.with_manager:
            self.manager = TicTocManager()  # 获取单例实例
        self.start_time = time.time()

    def tic(self):
        """启动计时"""
        self.start_time = time.time()

    def toc(self):
        """停止计时并记录"""
        duration = (time.time() - self.start_time) * 1000  # 转换为毫秒
        print(f"[{self.msg}] 耗时: {duration:.2f} ms")
        if self.with_manager:
            self.manager.record(self.msg, duration)
        return duration

def TicTocDecorator(func):
    """装饰器，用于自动记录函数运行时间"""
    def wrapper(*args, **kwargs):
        tic = TicToc(func.__name__)
        result = func(*args, **kwargs)
        toc = tic.toc()
        return result, toc
    return wrapper

# 使用示例
if __name__ == "__main__":
    manager = TicTocManager()
    manager.load_from_files(["ego_drive.json","focal_ego_drive.json"])
    manager.plot_comparison('ggg')
    # # 初始化多个计时器
    # timer1 = TicToc("算法A")
    # timer2 = TicToc("算法B")
    #
    # # 模拟多次运行
    # for i in range(3):
    #     timer1.tic()
    #     time.sleep(0.1 * (i + 1))  # 模拟算法A运行时间增长
    #     timer1.toc()
    #
    #     timer2.tic()
    #     time.sleep(0.08 * (i + 1))  # 模拟算法B运行时间增长
    #     timer2.toc()
    #
    # # 保存数据并绘图
    # manager = TicTocManager()
    # manager.save_to_file("performance_data.json")
    # manager.plot_comparison()